﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
using System.Reflection;

namespace MVCToolkit.Validations
{
    [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
    public class Comparer : ValidationAttribute, IClientValidatable
    {
        private OperatorMetadata _metadata;
        private readonly string _dependentPropertyName;
        private readonly ComparisionOperator _comparisionOperator;

        public Comparer(string dependentPropertyName, ComparisionOperator comparisionOperator)
        {
            _dependentPropertyName = dependentPropertyName;
            _comparisionOperator = comparisionOperator;
            _metadata = OperatorMetadata.Get(comparisionOperator);
            ErrorMessage = "{0} must be " + _metadata.ErrorMessage + " {1}.";
        }

        public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata,
                                 ControllerContext context)
        {
            //This is not complete logic, need to revisit
            var rule = new ModelClientValidationRule();
            rule.ErrorMessage = FormatErrorMessage(metadata.GetDisplayName());
            rule.ValidationParameters.Add("other", _dependentPropertyName);
            rule.ValidationType = "comparer";
            yield return rule;
        }

        public override string FormatErrorMessage(string name)
        {
            return string.Format(ErrorMessageString, name, _dependentPropertyName);
        }

        protected override System.ComponentModel.DataAnnotations.ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            if (value != null)
            {
                PropertyInfo dependentPropertyInfo = validationContext.ObjectType.GetProperty(_dependentPropertyName);

                if (dependentPropertyInfo == null)
                {
                    return new System.ComponentModel.DataAnnotations.ValidationResult("Unknown property to compare", new[] { _dependentPropertyName });
                }

                object dependentPropertyValue = dependentPropertyInfo.GetValue(validationContext.ObjectInstance, null);

                if (dependentPropertyValue != null)
                {
                    if (!_metadata.IsValid(value, dependentPropertyValue))
                    {
                        return new System.ComponentModel.DataAnnotations.ValidationResult(FormatErrorMessage(validationContext.DisplayName));
                    }
                }
            }
            return System.ComponentModel.DataAnnotations.ValidationResult.Success;
        }
    }
}
